/****************************************************************************
 * Chariott - Continuous Integration Testing Tool
 * Zaid Mohsin
 * The University of York
 * 2012/2013
 * MSc in Information Technology
 * All rights reserved.
 ****************************************************************************/
package chariott.JUnit;

import static org.junit.Assert.*;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.commons.collections.MultiMap;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

import chariott.configuration.ConfigResolver;
import chariott.partition.AlgorithmOrder;
import chariott.partition.RoundRobinOrder;
import chariott.testing.AntScriptGenerator;
import chariott.testing.CostEffectiveAlgorithmSelector;
import chariott.testing.RunItem;
import chariott.testing.ScriptGenerator;
import chariott.testing.TestCase;

/**
 * JUnit test suite to test the Script Generator and componenets in
 * chariott.testing package.
 * 
 * @author Zaid
 * 
 */
public class ScriptGeneratorTest {

	private ArrayList myList;

	@Before
	public void setUp() throws Exception {
		// parse the configurations file
		ConfigResolver resolver = new ConfigResolver(new File(
				"chariottconfig.ini"));

		// clean up the generated files folder
		// delete the script files created
		File dir = new File("generatedScripts");
		for (File file : dir.listFiles())
			file.delete();

		// create the TestCase objects
		TestCase myCase1 = new TestCase("test1", 3.0);
		TestCase myCase2 = new TestCase("test2", 2.0);
		myList = new ArrayList<RunItem>();
		myList.add(myCase1);
		myList.add(myCase2);

	}

	@After
	public void tearDown() {
		// delete the script files created
		File dir = new File("generatedScripts");
		for (File file : dir.listFiles())
			file.delete();

	}

	// test to check if the AntScriptGenerator generates a script.
	@Test
	public void checkFileOutputExists() {

		ScriptGenerator myGen = new AntScriptGenerator(1, myList);
		myGen.generate();

		File f = new File("generatedScripts/chariott-test0.xml");

		// check if generated file exsists
		assertTrue(f.exists());
	}

	// test if correct number of scripts is generated according to number of
	// nodes
	@Test
	public void checkNumberOfFiles() {
		ScriptGenerator myGen = new AntScriptGenerator(2, myList);
		myGen.generate();

		// check if two files are generated
		assertTrue(new File("generatedScripts").listFiles().length == 2);

	}

	// test if test1 case is written in the JUnit directive in the Ant Script
	@Test
	public void checkTestCaseInsertion() {
		ScriptGenerator myGen = new AntScriptGenerator(1, myList);
		myGen.generate();
		boolean exists = false;
		File file = new File("generatedScripts/chariott-test0.xml");

		Scanner scanner = null;
		try {
			scanner = new Scanner(file);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		// scan the file to check if test2 was added
		while (scanner.hasNextLine()) {
			String line = scanner.nextLine();
			if (line.contains("test2"))
				exists = true;
		}

		assertTrue(exists);

	}

	// check if the xml generated is well formed
	@Test
	public void checkXML() {
		ScriptGenerator myGen = new AntScriptGenerator(1, myList);
		myGen.generate();

		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		factory.setValidating(false);
		factory.setNamespaceAware(true);

		DocumentBuilder builder = null;
		try {
			builder = factory.newDocumentBuilder();
		} catch (ParserConfigurationException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}

		// the "parse" method also validates XML, will throw an exception if
		// misformatted
		try {
			Document document = builder.parse(new InputSource(
					"generatedScripts/chariott-test0.xml"));
		} catch (SAXParseException e) {
			fail(e.getMessage());
		} catch (SAXException e) {
			fail(e.getMessage());
		} catch (IOException e) {
			fail(e.getMessage());
		}

		assertTrue(true);
	}

	// test if round robin is the most cost effective method using the algorithm
	// selector.
	@Test
	public void checkAlgorithmSelector() {
		myList.add(new TestCase("newCase", 2.0));

		MultiMap mm = CostEffectiveAlgorithmSelector.INSTANCE.getBestAlgorithm(
				2, myList);
		AlgorithmOrder rr = new RoundRobinOrder(2, myList);

		assertTrue(mm.equals(rr.generateRuns()));

	}
}
